package com.darwin.darwinBitmapEngine.core
{
	import com.darwin.darwinBitmapEngine.events.NodeEvent;
	import com.darwin.darwinBitmapEngine.map.CanvasMap;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * 用于2D渲染的画布 
	 * @author lipi
	 */
	public class Canvas extends Bitmap implements IContainer
	{
		/**
		 * 
		 * @param canvasWidth 画布宽度，水平有多少像素
		 * @param canvasHeight 画布高度，垂直有多少像素
		 * @param transparent 是否允许透明
		 * @param fillColor 填充的颜色值
		 */
		public function Canvas(canvasWidth:int,canvasHeight:int,transparent:Boolean = true,fillColor:uint = 0)
		{
			super(null,"auto",false);
			
			_bitmapData = new BitmapData(canvasWidth,canvasHeight,transparent,fillColor);
			this.bitmapData = _bitmapData;
			
			_fillColor = fillColor;
			_transparent = transparent;
			_canvasWidth = canvasWidth;
			_canvasHeight = canvasHeight;
			
			_canvasMap = new CanvasMap();
			
		}
		
		private var _bitmapData:BitmapData;
		
		
		private var _canvasResize:Boolean = false;
		
		//填充色 
		private var _fillColor:uint;
		
		//背景是否透明 
		private var _transparent:Boolean;
		
		
		//上一次鼠标移上的对象
		private var _preOverNode:INode;
		
		/**
		 * 设置鼠标移动。如果鼠标移动，将鼠标的全局位置传入对子节点进行鼠标事件处理
		 * @param x 全局x坐标
		 * @param y 全局y坐标
		 */
		public function setMouseMove(x:Number,y:Number):INode
		{
			var nodeList:Vector.<INode> = getNodesForXY(x,y);
			var $hitNode:INode;
			
			//取得鼠标移到的node
			if(nodeList != null && nodeList.length>0) 
			{
				for(var i:int = nodeList.length-1;i>=0;i--)
				{
					if(nodeList[i].mouseHoverEnabled == true)
					{ //需要判断鼠标移动是否允许
						$hitNode = nodeList[i];
						break;
					}
				}
			}
			
			//mouse out事件判断
			if($hitNode != _preOverNode && _preOverNode != null)
			{//如果上一个对象存在则执行MOUSE_OUT事件 
				var $nodeOutEvent:NodeEvent = new NodeEvent(NodeEvent.MOUSE_OUT);
				$nodeOutEvent.nodeTarget = _preOverNode;
				if(_preOverNode.parentContainer is ContainerNode)
				{
					$nodeOutEvent.containerTarget = _preOverNode.parentContainer;
					(_preOverNode.parentContainer as ContainerNode).dispatchEvent($nodeOutEvent);
				}else{
					_preOverNode.dispatchEvent($nodeOutEvent);
				}
				dispatchEvent($nodeOutEvent);
			}
			
			//mouse over事件判断
			if($hitNode != _preOverNode && $hitNode != null)
			{//如果移动的对象还是上一个节点则忽略
				//执行MOUSE_OVER事件
				var $nodeEvent:NodeEvent = new NodeEvent(NodeEvent.MOUSE_OVER);
				$nodeEvent.nodeTarget = $hitNode;
				if($hitNode.parentContainer is ContainerNode)
				{
					$nodeEvent.containerTarget = $hitNode.parentContainer;
					($hitNode.parentContainer as ContainerNode).dispatchEvent($nodeEvent);
				}else{
					$hitNode.dispatchEvent($nodeEvent);
				}
				dispatchEvent($nodeEvent);
			}
			_preOverNode = $hitNode;
			return $hitNode;
		}
		
		/**
		 *	 设置鼠标按下。如果鼠标按下，将鼠标的全局位置传入对子节点进行鼠标事件处理
		 * @param x 全局x坐标 
		 * @param y 全局y坐标
		 * @return 
		 * 
		 */
		public function setMouseDown(x:Number,y:Number):INode
		{
			var nodeList:Vector.<INode> = getNodesForXY(x,y);
			
			if(nodeList != null && nodeList.length>0) 
			{
				for(var i:int = nodeList.length-1;i>=0;i--)
				{
					if(nodeList[i].clickEnabled == true)
					{
						var $nodeEvent:NodeEvent = new NodeEvent(NodeEvent.MOUSE_DOWN);
						$nodeEvent.nodeTarget = nodeList[i];
						if(nodeList[i].parentContainer is ContainerNode)
						{
							$nodeEvent.containerTarget = nodeList[i].parentContainer;
							(nodeList[i].parentContainer as ContainerNode).dispatchEvent($nodeEvent);
						}else{
							nodeList[i].dispatchEvent($nodeEvent);
						}
						dispatchEvent($nodeEvent);
						return nodeList[i];
					}
				}
			}
			return null;
		}
		
		/**
		 * 设置鼠标点击。如果鼠标单击，将鼠标的全局位置传入对子节点进行鼠标事件处理
		 * @param x 全局x坐标 
		 * @param y 全局y坐标
		 */
		public function setClick(x:Number,y:Number):INode
		{
			var nodeList:Vector.<INode> = getNodesForXY(x,y);
			
			if(nodeList != null && nodeList.length>0) 
			{
				for(var i:int = nodeList.length-1;i>=0;i--)
				{
					if(nodeList[i].clickEnabled == true)
					{
						var $nodeEvent:NodeEvent = new NodeEvent(NodeEvent.MOUSE_CLICK);
						$nodeEvent.nodeTarget = nodeList[i];
						if(nodeList[i].parentContainer is ContainerNode)
						{
							$nodeEvent.containerTarget = nodeList[i].parentContainer;
							(nodeList[i].parentContainer as ContainerNode).dispatchEvent($nodeEvent);
						}else{
							nodeList[i].dispatchEvent($nodeEvent);
						}
						dispatchEvent($nodeEvent);
						return nodeList[i];
					}
				}
			}
			return null;
		}
		
		//取得位置上的列表
		private function getNodesForXY(x:Number,y:Number):Vector.<INode>
		{
			var $x:Number = x - this.x;
			var $y:Number = y - this.y;
			
			$x = $x/scale - contentX;
			$y = $y/scale - contentY;
			
			var nodeList:Vector.<INode> = _canvasMap.getNodesForXY($x,$y);
			return nodeList;
		}
		
		
///////////////////////////////////////////////////
		
		//显示列表操作
		
//////////////////////////////////////////////////
		
		// 
		
		
		private var _contentX:Number = 0;
		/**
		 * Canvas偏移的X轴，即Canvas的坐标原点与可见点X距离
		 */
		public function set contentX(value:Number):void
		{
			_contentX = value;
			_renderFlag = true;
		}
		
		public function get contentX():Number
		{
			return _contentX;
		}
		
		private var _contentY:Number = 0;

		/**
		 *  Canvas偏移的Y轴，即Canvas的坐标原点与可见点Y距离
		 */
		public function get contentY():Number
		{
			return _contentY;
		}

		public function set contentY(value:Number):void
		{
			_contentY = value;
			_renderFlag = true;
		}
		
		
		private var _canvasWidth:int = 0;

		/**
		 * 画布的宽度
		 */
		public function get canvasWidth():int
		{
			return _canvasWidth;
		}

		public function set canvasWidth(value:int):void
		{
			_canvasWidth = value;
			_canvasResize = true;
			_renderFlag = true;
		}

		private var _canvasHeight:int = 0;

		/**
		 * 画布的高度 
		 */
		public function get canvasHeight():int
		{
			return _canvasHeight;
		}

		public function set canvasHeight(value:int):void
		{
			_canvasHeight = value;
			_canvasResize = true;
			_renderFlag = true;
		}
		
		private var _canvasMap:CanvasMap;
		
		/**
		 * @return 返回列表项个数
		 */
		public function get numChildren():uint
		{
			return _canvasMap.numChildren;
		}
		
		/**
		 * 添加一个显示对象到显示列表
		 * @param node 对象节点
		 * @return 返回对象节点
		 */
		public function addNode(node:INode):INode
		{
			if(node.parentContainer != null) node.parentContainer.removeNode(node);
			_canvasMap.addNode(node);
			node.parentContainer = this;
			_renderFlag = true;
			return node;
		}
		
		/**
		 * 删除一个节点
		 * @param node 要删除的节点
		 * @return 被删除的节点
		 */
		public function removeNode(node:INode):INode
		{
			node.parentContainer = null;
			_renderFlag = true;
			return _canvasMap.removeNode(node);
		}
		
		
		/**
		 * 添加一个节点到某个索引
		 * @param node 要添加的节点 
		 * @param index 要加到的索引
		 * @return 添加的节点
		 */
		public function addNodeAt(node:INode,index:int):INode
		{
			_canvasMap.addNodeAt(node,index);
			if(node.parentContainer != null) node.parentContainer.removeNode(node);
			node.parentContainer = this;
			_renderFlag = true;
			return node;
		}
		
		/**
		 * 删除某个索引的节点
		 * @param index
		 * @return 
		 */
		public function removeNodeAt(index:int):INode
		{
			var $node:INode = _canvasMap.removeNodeAt(index);
			$node.parentContainer = null;
			_renderFlag = true;
			return $node;
			
		}
		
		
		/**
		 * 取得位于某个索引中的节点
		 * @param index 索引值
		 * @return 返回某个索引的节点
		 */
		public function getNodeAt(index:int):INode
		{
			return _canvasMap.getNodeAt(index);
		}
		
		
		/**
		 * 如果一个节点位置和大小改变则标记它
		 */
		public function markChange(node:INode):INode
		{
			_canvasMap.addChangeNode(node);
			_renderFlag = true;
			return node;
		}
		
		/**
		 * 返回显示对象列表
		 */
		public function get nodeList():INodeList
		{
			return _canvasMap.nodeList;
		}
		
		/**
		 * 设置节点列表类型,即注入的类型
		 */
		public function setNodeListType(list:INodeList):void
		{
			_canvasMap.setNodeListType(list);
		}
		
		
//\\\显示列表结束\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		
		
		
		private var _point:Point = new Point();
		private var t:int = 0;
		
		private var _renderFlag:Boolean = true;

		/**
		 *	 是否渲染标记，如果_renderFlag标记为false则执行render不会进行渲染
		 */
		public function get renderFlag():Boolean
		{
			return _renderFlag;
		}

		/**
		 * @private
		 */
		public function set renderFlag(value:Boolean):void
		{
			_renderFlag = value;
		}
		
		private var _scale:Number = 1;

		/**
		 * 对画布缩放
		 */
		public function get scale():Number
		{
			return _scale;
		}

		public function set scale(value:Number):void
		{
			_scale = value;
		}
		

		/**
		 * 进行一次渲染
		 */
		public function render():void
		{
			if(_renderFlag == false)
			{
				return;
			}else{
				_renderFlag = false;
			}
			if(_canvasResize)
			{//如果画布大小改变则重新申请一张bitmapData
				if(_bitmapData != null)
				{
					_bitmapData.dispose();
					_bitmapData = null;
				}
				_bitmapData = new BitmapData(canvasWidth,canvasHeight,_transparent,_fillColor);
				this.bitmapData = _bitmapData;
				_canvasResize = false;
			}else{
				_bitmapData.fillRect(_bitmapData.rect,_fillColor);
			}
			
			var $renderNotifyList:Vector.<INode> = new Vector.<INode>();
//			var length:int = _canvasMap.numChildren;
			for(var i:int = 0;i<_canvasMap.numChildren;i++)
			{
				var $node:INode = _canvasMap.getNodeAt(i);
				if($node is ContainerNode)
				{
					var $container:ContainerNode = $node as ContainerNode;
					var $numChilder:int = $container.numChildren;
					for(var j:int = 0;j<$numChilder;j++)
					{
						var $childNode:INode = $container.getNodeAt(j);
						$childNode.render();
						if($childNode.renderNotify)
						{
							$renderNotifyList.push($childNode);
						}
						if($childNode.rect == null) continue;
						if($container.visible == false) continue;
						if($childNode.visible == false) continue;
						if($childNode.bitmapData != null)
						{
							if(scale == 1)
							{
								var $pt:Point = new Point($node.x + $childNode.x+contentX,$node.y + $childNode.y+contentY);
								_bitmapData.copyPixels($childNode.bitmapData,$childNode.rect,$pt,null,null,true); //原始
							}else{
								var $ptX:Number = ($node.x + $childNode.x+contentX)*scale;
								var $ptY:Number = ($node.y + $childNode.y+contentY)*scale;
								var $r:Rectangle = $childNode.rect.clone();
								$r.offset($ptX,$ptY);
								_bitmapData.draw($childNode.bitmapData,new Matrix(scale,0,0,scale,$ptX,$ptY),null,null,null,true);
							}
						}
					}
					//TODO 为何父容器不执行 render()?
					$container.render();
					if($container.renderNotify)
					{
						$renderNotifyList.push($container);
					}
				}else{
					$node.render();
					if($node.renderNotify)
					{
						$renderNotifyList.push($node);
					}
					if($node.visible == false) continue;
					if($node.rect == null) continue;
					if($node.bitmapData != null)
					{
						if(scale == 1)
						{
							_bitmapData.copyPixels($node.bitmapData,$node.rect,new Point($node.x+contentX,$node.y+contentY),null,null,true);
						}else{
							var $spt:Point = new Point(($node.x+contentX)*scale,($node.y+contentY)*scale);
							var $r2:Rectangle = $node.rect.clone();
							$r2.offset($spt.x,$spt.y);
							_bitmapData.draw($node.bitmapData,new Matrix(scale,0,0,scale,$spt.x,$spt.y),null,null,null,true);
						}
					}//if
				}//if
			}//for
			this.bitmapData = _bitmapData;
			for (var k:int = 0; k < $renderNotifyList.length; k++) 
			{
				$renderNotifyList[k].exeRenderNotify();
				$renderNotifyList[k].renderNotify = false;
			}
			
		}
		
		
	}
}